var AppalachianDB = {};

AppalachianDB.isInitialized = function() {
	var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
	var init = false;
        if (prefs.prefHasUserValue("extensions.appalachian.initialized")) {
		init = prefs.getBoolPref("extensions.appalachian.initialized");
	} else {
		prefs.setBoolPref("extensions.appalachian.initialized", init);
	}
	return init;
};

AppalachianDB.error = function(e) {
	var bundle = document.getElementById("appalachian-db-bundle");
	var prefix = bundle.getString("sqlerror");
	alert(prefix + " " + e);
};

AppalachianDB.init = function() {
	var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
	var prefix = "extensions.appalachian.";
	// check if initialized
	if (!AppalachianDB.isInitialized()) {
		// set some default pref values
	        if (!prefs.prefHasUserValue(prefix + "defaultID")) {
			prefs.setIntPref(prefix + "defaultID", -1);
		}
	        if (!prefs.prefHasUserValue(prefix + "useDefault")) {
			prefs.setBoolPref(prefix + "useDefault", true);
		}
	        if (!prefs.prefHasUserValue(prefix + "showInStatusBar")) {
			prefs.setBoolPref(prefix + "showInStatusBar", true);
		}
		// get and run SQL from properties files
		var db = AppalachianDB.getHandle();
		var creationBundle = document.getElementById("creation-bundle");
		var createOpenIDSQL = creationBundle.getString("idcreation");
		var createServerSQL = creationBundle.getString("servercreation");
		var urlMapSQL = creationBundle.getString("usecreation");
		var dbBundle = document.getElementById("appalachian-db-bundle");
		var initFailure = dbBundle.getString("direfailure");
		try {
			db.executeSimpleSQL(createOpenIDSQL);
			db.executeSimpleSQL(createServerSQL);
			db.executeSimpleSQL(urlMapSQL);
			prefs.setBoolPref("extensions.appalachian.initialized", true);
		} catch (e) {
			alert(initFailure + " " + e);
			dump(e);
		}
	} else {
		// sigh; check if prefs exist
	        if (!prefs.prefHasUserValue(prefix + "defaultID")) {
			prefs.setIntPref(prefix + "defaultID", -1);
		}
	        if (!prefs.prefHasUserValue(prefix + "useDefault")) {
			prefs.setBoolPref(prefix + "useDefault", true);
		}
	        if (!prefs.prefHasUserValue(prefix + "showInStatusBar")) {
			prefs.setBoolPref(prefix + "showInStatusBar", true);
		}
	}
};

AppalachianDB.getQuery = function(key) {
	var bundle = document.getElementById("appalachian-query-bundle");
	var sql = bundle.getString(key);
	return sql;
};

AppalachianDB.getFile = function() {
	var file = Components.classes["@mozilla.org/file/directory_service;1"]
        	.getService(Components.interfaces.nsIProperties)
		.get("ProfD", Components.interfaces.nsIFile);
	file.append("appalachian.sqlite");
	return file;
};

AppalachianDB.getHandle = function() {
	var file = AppalachianDB.getFile();
	var storageService = Components.classes["@mozilla.org/storage/service;1"]
		.getService(Components.interfaces.mozIStorageService);
	var mDBConn = storageService.openDatabase(file);
	return mDBConn;
};

AppalachianDB.cosmeticListAll = function() {
	if (AppalachianDebug.enabled()) AppalachianDebug.trace("db.js", "> cosmeticListAll");
	var results = new Array();
	if (!AppalachianDB.isInitialized()) return results;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("cosmeticListAll");
	var st = db.createStatement(query);
	var info = null;
	try {
		while (st.executeStep()) {
			var id = st.getInt32(0);
			var url = st.getUTF8String(1);
			var use = st.getUTF8String(2);
			info = new OpenID(id, url, use);
			results.push(info);
		}
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	if (AppalachianDebug.enabled()) AppalachianDebug.trace("db.js", "< cosmeticListAll");
	return results;
};

AppalachianDB.listAll = function() {
	if (AppalachianDebug.enabled()) AppalachianDebug.trace("db.js", "> listAll");
	var results = new Array();
	if (!AppalachianDB.isInitialized()) return results;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("listAll");
	var st = db.createStatement(query);
	var oldid = -1;
	var servers = [];
	var info = null;
	try {
		while (st.executeStep()) {
			var id = st.getInt32(0);
			var url = st.getUTF8String(1);
			var use = st.getUTF8String(2);
			var server = st.getUTF8String(3);
			if (results.length == 0 && oldid == -1) {
				oldid = id;
				info = new OpenID(id, url, use, [server]);
			} else if (id != oldid) {
				results.push(info);
				oldid = id;
				info = new OpenID(id, url, use, [server]);
			} else {
				info.addServer(server);
			}
		}
		if (info != null) {
			results.push(info);
		}
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	if (AppalachianDebug.enabled()) AppalachianDebug.trace("db.js", "< listAll");
	return results;
};

AppalachianDB.countServers = function(id) {
	var result;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("countServers");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		st.executeStep();
		result = st.getInt32(0);
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return result;
};

AppalachianDB.listServers = function(id) {
	var results = new Array();
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("listServers");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		while (st.executeStep()) {
			var id = st.getInt32(0);
			var server = st.getUTF8String(1);
			var server = { "id" : id, "server" : server };
			results.push(server);
		}
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return results;
};

AppalachianDB.listUses = function(id) {
	var results = new Array();
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("listUses");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		while (st.executeStep()) {
			var useid = st.getInt32(0);
			var url = st.getUTF8String(1);
			var field = st.getInt32(2);
			var form = st.getInt32(3);
			var use = { "id" : useid, "url" : url, "field" : field, "form" : form };
			results.push(use);
		}
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return results;
};

AppalachianDB.getUse = function(useid, openid) {
	var result;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("getUse");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, useid);
		st.bindInt32Parameter(1, openid);
		st.executeStep();
		var field = st.getInt32(2);
		var form = st.getInt32(3);
		result = { "use_id" : useid, "openid" : openid, "field" : field, "form" : form };
	} catch(e) {
		AppalachianDB.error("getUse:" + e);
	} finally {
		st.reset();
	}
	return result;
};

AppalachianDB.anyUseExists = function(url) {
	var result = false;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("anyUseExists");
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, AppalachianDB.normalizeUrl(url));
		while (st.executeStep()) {
			var count = st.getInt32(0);
			result = count > 0;
		}
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return result;
}

AppalachianDB.listUsesIds = function(url) {
	var results = new Array();
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("listUsesIds");
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, url);
		while (st.executeStep()) {
			var id = st.getInt32(0);
			var openid = st.getInt32(1);
			var field = st.getInt32(2);
			var form = st.getInt32(3);
			var id_use = { "use_id" : id, "openid" : openid, "field" : field, "form" : form };
			results.push(id_use);
		}
	} catch(e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return results;
};

AppalachianDB.getInfo = function(id) {
	var info;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("getInfo");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		var servers = [];
		while (st.executeStep()) {
			var url = st.getUTF8String(0);
			var use = st.getUTF8String(1);
			var server = st.getUTF8String(2);
			servers.push(server);
		}
		info = new OpenID(id, url, use, servers);
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return info;
};

AppalachianDB.getServerInfo = function(id) {
	var info;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("getServerInfo");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		st.executeStep();
		var server = st.getUTF8String(0);
		info = { url : server };
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return info;
};

AppalachianDB.getInfoByUrl = function(url) {
	var out;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("idrow");
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, url);
		st.executeStep();
		out = st.getInt32(0);
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return out;
};

AppalachianDB.exists = function(url) {
	var out = false;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("idExists");	
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, url);
		st.executeStep();
		var count = st.getInt32(0);
		out = count > 0;
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return out;
};

AppalachianDB.add = function(url, use, servers, cont) {
	if (AppalachianDebug.enabled()) AppalachianDebug.trace("db.js", "> add " + url + " " + use + " " + servers);
	var dbBundle = document.getElementById("appalachian-db-bundle");
	var failmsg = dbBundle.getString("existserror");
	if (AppalachianDB.exists(url)) throw (failmsg);
	var id;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("addOpenid");
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, url);
		st.bindUTF8StringParameter(1, use);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}

	query = AppalachianDB.getQuery("idrow");
	st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, url);
		st.executeStep();
		id = st.getInt32(0);
	} catch (e) {
		AppalachianDB.error(e);
	}

	for (var i = 0; i < servers.length; i++) {
		query = AppalachianDB.getQuery("addServer");
		st = db.createStatement(query);
		try {
			st.bindInt32Parameter(0, id);
			st.bindUTF8StringParameter(1, servers[i]);
			st.execute();
		} catch (e) {
			AppalachianDB.error(e);
		}
	}
	
	if (AppalachianDebug.enabled()) AppalachianDebug.trace("db.js", "< add");
	if (cont) {
		cont(id);
	} else {
		return id;
	}
};

AppalachianDB.serverExists = function(openid, server) {
	var out = false;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("serverExists");	
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, openid);
		st.bindUTF8StringParameter(1, server);
		st.executeStep();
		var count = st.getInt32(0);
		out = count > 0;
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return out;
};

AppalachianDB.addServer = function(openid, server) {
	var dbBundle = document.getElementById("appalachian-db-bundle");
	var failmsg = dbBundle.getString("serverexistserror");
	if (AppalachianDB.serverExists(openid, server)) throw (failmsg);
	var id;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("addServer");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, openid);
		st.bindUTF8StringParameter(1, server);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

AppalachianDB.useExists = function(openid ,url) {
	var out = false;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("useExists");	
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, openid);
		st.bindUTF8StringParameter(1, url);
		st.executeStep();
		var count = st.getInt32(0);
		out = count > 0;
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return out;
};

AppalachianDB.getUseId = function(openid ,url) {
	var out;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("getUseId");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, openid);
		st.bindUTF8StringParameter(1, url);
		st.executeStep();
		var out = st.getInt32(0);
	} catch (e) {
		AppalachianDB.error(e);
	} finally {
		st.reset();
	}
	return out;
};

AppalachianDB.normalizeUrl = function(url) {
	// remove # frags, or anything else necessary when dealing with
	// internal URLs; currently for recorded sites *only*
	var normal = url;
	if (url.indexOf('#') > 0) {
		normal = url.substring(0, url.indexOf('#'));
	}
	return normal;
}

AppalachianDB.recordUse = function(openid, url, field, form) {
	url = AppalachianDB.normalizeUrl(url);
	if (AppalachianDB.useExists(openid, url)) return;
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("recordUse");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, openid);
		st.bindUTF8StringParameter(1, url);
		st.bindInt32Parameter(2, field);
		st.bindInt32Parameter(3, form);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

AppalachianDB.modify = function(id, url, use) {
	var dbBundle = document.getElementById("appalachian-db-bundle");
	var failmsg = dbBundle.getString("existserror");
	if (AppalachianDB.exists(url)) throw (failmsg);
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("modifyOpenid");
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, url);
		st.bindUTF8StringParameter(1, use);
		st.bindInt32Parameter(2, id);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

AppalachianDB.modifyServer = function(id, openid, server) {
	var dbBundle = document.getElementById("appalachian-db-bundle");
	var failmsg = dbBundle.getString("serverexistserror");
	if (AppalachianDB.serverExists(openid, server)) throw (failmsg);
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("modifyServer");
	var st = db.createStatement(query);
	try {
		st.bindUTF8StringParameter(0, server);
		st.bindInt32Parameter(1, id);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

AppalachianDB.deleteServer = function(id) {
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("deleteServerById");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

AppalachianDB.delete = function(id) {
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("deleteServerByOpenid");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}

	query = AppalachianDB.getQuery("delete");
	st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, id);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

AppalachianDB.deleteUse = function(useid) {
	var db = AppalachianDB.getHandle();
	var query = AppalachianDB.getQuery("deleteUse");
	var st = db.createStatement(query);
	try {
		st.bindInt32Parameter(0, useid);
		st.execute();
	} catch (e) {
		AppalachianDB.error(e);
	}
};

// completely destroy the entire database
AppalachianDB.wipe = function() {
	var file = AppalachianDB.getFile();
	file.remove(false);
	var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
	prefs.clearUserPref("extensions.appalachian.initialized");
	prefs.clearUserPref("extensions.appalachian.defaultID");
};
